// ------------------------------------------------------------------------
// 项目名称：Canroc.Net 
// 版权归属：Canroc（https://gitee.com/canroc）
//
// 许可证信息
// Canroc.Net项目主要遵循 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-APACHE 文件。
//
// 使用条款：
// 1.使用本项目应遵守相关法律法规和许可证的要求。
// 2.不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动。
// 3.任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任
//
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
//
// 其他重要信息
// Canroc.Net 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// ------------------------------------------------------------------------

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.Data;
using System.Reflection;
using System.Text.RegularExpressions;

namespace Canroc.Net.Core.Helper;

/// <summary>
///     Open XML 帮助类
/// </summary>
public static partial class OpenXmlHelper
{
    [GeneratedRegex(@"\{\{|\}\}")]
    private static partial Regex TemplateCellOccupyRegex();

    /// <summary>
    ///     读取Excel文件到DataTable
    /// </summary>
    /// <param name="stream">文件流</param>
    /// <returns></returns>
    public static DataTable QueryAsDataTable(Stream stream)
    {
        using var document = SpreadsheetDocument.Open(stream, false);
        var workbookPart = document.WorkbookPart!;
        var worksheetPart = workbookPart.WorksheetParts.First();
        var worksheet = worksheetPart.Worksheet;
        var sheetData = worksheet.GetFirstChild<SheetData>()!;

        var dt = new DataTable();
        var rows = sheetData.Elements<Row>().ToList();

        if (rows.Count == 0) return dt;

        // 构建表头
        var headerRow = rows.First();
        var cells = headerRow.Elements<Cell>().ToList();
        foreach (var cellValue in cells.Select(cell => GetCellValue(cell, workbookPart)))
        {
            dt.Columns.Add(new DataColumn(cellValue));
        }

        // 填充表格数据
        for (var i = 1; i < rows.Count; i++)
        {
            var row = rows[i];
            var dataRow = dt.NewRow();
            var dataCells = row.Elements<Cell>().ToList();

            for (var j = 0; j < dataCells.Count && j < dt.Columns.Count; j++)
            {
                var cellValue = GetCellValue(dataCells[j], workbookPart);
                dataRow[j] = cellValue;
            }

            dt.Rows.Add(dataRow);
        }

        return dt;
    }

    /// <summary>
    ///     生成Excel模板文件
    /// </summary>
    /// <param name="templatePath">模版位置</param>
    /// <param name="list">集合</param>
    /// <returns></returns>
    public static async Task<MemoryStream> GenerateExcelAsync<T>(string templatePath, List<T> list)
    {
        var templateBytes = await File.ReadAllBytesAsync(templatePath);
        var memoryStream = new MemoryStream();
        await memoryStream.WriteAsync(templateBytes);

        memoryStream.Position = 0;
        using (var document = SpreadsheetDocument.Open(memoryStream, true, new OpenSettings { AutoSave = true }))
        {
            var workbookPart = document.WorkbookPart!;
            var worksheetPart = workbookPart.WorksheetParts.First();
            var worksheet = worksheetPart.Worksheet;
            var sheetData = worksheet.GetFirstChild<SheetData>()!;

            var templateRow = FindDataTemplateRow(workbookPart, sheetData);
            if (templateRow != null && list.Count != 0)
            {
                var columnsMeta = BuildColumnMetadata(templateRow, workbookPart);
                templateRow.Remove();

                var dataResult = RenderDataBlocks(list, sheetData, templateRow, columnsMeta);
                var sumTemplateRow = FindSumTemplateRow(workbookPart, sheetData);
                if (sumTemplateRow != null)
                {
                    RenderSumRow(list, sheetData, sumTemplateRow, dataResult.NextRowIndex, workbookPart);
                }

                ApplyMergedRegions(worksheet, dataResult.MergedRegions);
            }

            worksheetPart.Worksheet.Save();
            document.Save();
        }

        await memoryStream.FlushAsync();
        memoryStream.Position = 0;
        return memoryStream;
    }

    #region 内部函数

    /// <summary>
    ///     渲染数据块时返回的行索引与合并信息。
    /// </summary>
    private sealed record DataRenderResult(
        uint NextRowIndex,
        List<(uint startRow, uint endRow, int startCol, int endCol)> MergedRegions);

    /// <summary>
    ///     定位数据块使用的模板行（不包含合计占位）。
    /// </summary>
    private static Row? FindDataTemplateRow(WorkbookPart workbookPart, SheetData sheetData)
    {
        foreach (var row in sheetData.Elements<Row>().OrderByDescending(r => r.RowIndex!.Value))
        {
            var cells = row.Elements<Cell>().Take(10).ToList();
            if (cells.Count == 0) continue;

            var hasAnyValue = false;
            var hasTemplatePlaceholder = false;
            var hasSumPlaceholder = false;

            foreach (var text in cells.Select(cell => GetCellValue(cell, workbookPart))
                         .Where(text => !string.IsNullOrEmpty(text)))
            {
                hasAnyValue = true;
                if (text.Contains("{{") && text.Contains("}}"))
                    hasTemplatePlaceholder = true;
                if (text.Contains("Sum(", StringComparison.OrdinalIgnoreCase))
                    hasSumPlaceholder = true;
            }

            if (!hasAnyValue || !hasTemplatePlaceholder || hasSumPlaceholder) continue;
            return row;
        }

        return null;
    }

    /// <summary>
    ///     从模板行中解析列占位符并构建列元数据。
    /// </summary>
    private static List<ColumnMeta> BuildColumnMetadata(Row templateRow, WorkbookPart workbookPart)
    {
        var templateCells = templateRow.Elements<Cell>().ToList();
        var columnsMeta = new List<ColumnMeta>(templateCells.Count);

        foreach (var (cell, colIndex) in templateCells.Select((cell, index) => (cell, index)))
        {
            var rawText = GetCellValue(cell, workbookPart);
            var meta = new ColumnMeta
            {
                ColumnIndex = colIndex,
                TemplateCell = cell,
                RawText = rawText,
                Kind = ColumnKind.PlainText,
                ShouldMerge = false
            };

            if (!string.IsNullOrEmpty(rawText))
            {
                var inner = TemplateCellOccupyRegex().Replace(rawText, string.Empty).Trim();

                if (string.Equals(inner, "RowIndex", StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(inner, "RowNo", StringComparison.OrdinalIgnoreCase))
                {
                    meta.Kind = ColumnKind.RowIndex;
                    meta.ShouldMerge = false;
                }
                else if (inner.Contains("Sum(", StringComparison.OrdinalIgnoreCase))
                {
                    // Sum placeholders are handled by the sum-row logic.
                }
                else
                {
                    var parts = inner.Split('.', StringSplitOptions.RemoveEmptyEntries);
                    var idxWithArray = Array.FindIndex(parts, p => p.Contains("[]"));

                    if (idxWithArray >= 0 && parts.Length >= idxWithArray + 2)
                    {
                        meta.Kind = ColumnKind.CollectionProperty;
                        meta.IsCollection = true;
                        meta.CollectionPropertyName = parts[idxWithArray].Replace("[]", string.Empty);
                        meta.CollectionItemPropertyName = parts[idxWithArray + 1];
                        meta.ShouldMerge = false;
                    }
                    else
                    {
                        switch (parts.Length)
                        {
                            case 1:
                                meta.Kind = ColumnKind.SimpleProperty;
                                meta.PropertyName = parts[0];
                                meta.ShouldMerge = true;
                                break;
                            case >= 2:
                                meta.Kind = ColumnKind.NestedProperty;
                                meta.ParentPropertyName = parts[^2];
                                meta.ChildPropertyName = parts[^1];
                                meta.ShouldMerge = true;
                                break;
                        }
                    }
                }
            }

            columnsMeta.Add(meta);
        }

        return columnsMeta;
    }

    /// <summary>
    ///     根据列元数据与数据源渲染数据块并返回下一行索引及合并信息。
    /// </summary>
    private static DataRenderResult RenderDataBlocks<T>(IReadOnlyList<T> source, SheetData sheetData,
        Row templateRow, IReadOnlyList<ColumnMeta> columnsMeta)
    {
        var mergedRegions = new List<(uint startRow, uint endRow, int startCol, int endCol)>();
        var currentRowIndex = templateRow.RowIndex!.Value;
        var globalBlockCounter = 0;
        var entityType = typeof(T);

        foreach (var item in source)
        {
            globalBlockCounter++;
            var maxChildrenCount = 0;

            foreach (var meta in columnsMeta)
            {
                if (!meta.IsCollection)
                {
                    meta.CurrentChildren = null;
                    continue;
                }

                var prop = entityType.GetProperty(meta.CollectionPropertyName!);
                if (prop?.GetValue(item) is IList childrenList)
                {
                    meta.CurrentChildren = childrenList;
                    if (childrenList.Count > maxChildrenCount)
                    {
                        maxChildrenCount = childrenList.Count;
                    }
                }
                else
                {
                    meta.CurrentChildren = null;
                }
            }

            var blockRowCount = Math.Max(1, maxChildrenCount);
            var startRowIndex = currentRowIndex;
            var endRowIndex = startRowIndex + (uint)(blockRowCount - 1);

            for (var rowOffset = 0; rowOffset < blockRowCount; rowOffset++)
            {
                var rowIndex = startRowIndex + (uint)rowOffset;
                var row = CreateRowFromTemplate(templateRow, rowIndex);
                InsertRowOrdered(sheetData, row);

                foreach (var meta in columnsMeta)
                {
                    var cell = CreateCell(meta.TemplateCell, rowIndex, meta.ColumnIndex);
                    PopulateCell(meta, cell, rowOffset, globalBlockCounter, item, entityType);
                    row.Append(cell);
                }
            }

            if (blockRowCount > 1)
            {
                mergedRegions.AddRange(from meta in columnsMeta
                    where meta.ShouldMerge || meta.Kind == ColumnKind.RowIndex
                    select (startRowIndex, endRowIndex, meta.ColumnIndex, meta.ColumnIndex));
            }

            currentRowIndex = endRowIndex + 1;
        }

        return new DataRenderResult(currentRowIndex, mergedRegions);
    }

    /// <summary>
    ///     将对应列的值写入单元格（含集合、嵌套属性、行号等处理）。
    /// </summary>
    private static void PopulateCell<T>(ColumnMeta meta, Cell cell, int rowOffset, int blockIndex, T item,
        Type entityType)
    {
        switch (meta.Kind)
        {
            case ColumnKind.RowIndex:
                SetCellValue(cell, blockIndex);
                break;
            case ColumnKind.CollectionProperty:
                var listRef = meta.CurrentChildren;
                if (listRef != null && rowOffset < listRef.Count)
                {
                    var child = listRef[rowOffset];
                    if (child != null)
                    {
                        var childProp = child.GetType().GetProperty(meta.CollectionItemPropertyName!);
                        if (childProp != null)
                        {
                            var val = GetPropertyValue(childProp, child);
                            SetCellValue(cell, val);
                        }
                    }
                }

                break;
            case ColumnKind.SimpleProperty:
                if (rowOffset == 0 && item != null && !string.IsNullOrEmpty(meta.PropertyName))
                {
                    var prop = entityType.GetProperty(meta.PropertyName);
                    if (prop != null)
                    {
                        var val = GetPropertyValue(prop, item);
                        SetCellValue(cell, val);
                    }
                }

                break;
            case ColumnKind.NestedProperty:
                if (rowOffset == 0 && item != null && !string.IsNullOrEmpty(meta.ParentPropertyName) &&
                    !string.IsNullOrEmpty(meta.ChildPropertyName))
                {
                    var parentProp = entityType.GetProperty(meta.ParentPropertyName);
                    var parent = parentProp?.GetValue(item);
                    if (parent != null)
                    {
                        var childProp = parent.GetType().GetProperty(meta.ChildPropertyName);
                        if (childProp != null)
                        {
                            var val = GetPropertyValue(childProp, parent);
                            SetCellValue(cell, val);
                        }
                    }
                }

                break;
            case ColumnKind.PlainText:
            default:
                if (rowOffset == 0 && !string.IsNullOrEmpty(meta.RawText))
                {
                    SetCellValue(cell, meta.RawText);
                }

                break;
        }
    }

    /// <summary>
    ///     根据模板行复制样式并创建指定行索引的新行。
    /// </summary>
    private static Row CreateRowFromTemplate(Row templateRow, uint rowIndex)
    {
        var row = new Row { RowIndex = rowIndex };
        if (templateRow.Height != null)
            row.Height = templateRow.Height;
        if (templateRow.CustomHeight != null)
            row.CustomHeight = templateRow.CustomHeight;
        if (templateRow.Hidden != null)
            row.Hidden = templateRow.Hidden;
        if (templateRow.Collapsed != null)
            row.Collapsed = templateRow.Collapsed;
        if (templateRow.StyleIndex != null)
            row.StyleIndex = templateRow.StyleIndex;

        return row;
    }

    /// <summary>
    ///     保持按行号排序地插入行，避免行号错乱。
    /// </summary>
    private static void InsertRowOrdered(SheetData sheetData, Row row)
    {
        var nextRow = sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex!.Value > row.RowIndex!.Value);
        if (nextRow != null)
        {
            sheetData.InsertBefore(row, nextRow);
        }
        else
        {
            sheetData.Append(row);
        }
    }

    /// <summary>
    ///     查找包含合计占位符的模板行。
    /// </summary>
    private static Row? FindSumTemplateRow(WorkbookPart workbookPart, SheetData sheetData)
    {
        return (from row in sheetData.Elements<Row>().OrderByDescending(r => r.RowIndex!.Value)
            let cells = row.Elements<Cell>().Take(10).ToList()
            where cells.Count != 0
            where cells.Any(c => GetCellValue(c, workbookPart).Contains("Sum(", StringComparison.OrdinalIgnoreCase))
            select row).FirstOrDefault();
    }

    /// <summary>
    ///     根据模板渲染合计行并计算各 Sum 占位结果。
    /// </summary>
    private static void RenderSumRow<T>(IReadOnlyList<T> source, SheetData sheetData, Row sumTemplateRow,
        uint insertAtRowIndex, WorkbookPart workbookPart)
    {
        var sumTemplateCells = sumTemplateRow.Elements<Cell>().ToList();
        var sumRow = CreateRowFromTemplate(sumTemplateRow, insertAtRowIndex);
        InsertRowOrdered(sheetData, sumRow);

        foreach (var templateCell in sumTemplateCells.Select((c, idx) => new { Cell = c, Index = idx }))
        {
            var rawText = GetCellValue(templateCell.Cell, workbookPart);
            var cell = CreateCell(templateCell.Cell, insertAtRowIndex, templateCell.Index);
            var sumExpr = ExtractSumExpression(rawText);

            if (!string.IsNullOrEmpty(sumExpr))
            {
                var sumValue = CalculateSumValue(source, sumExpr);
                SetCellValue(cell, sumValue);
            }
            else if (!string.IsNullOrEmpty(rawText))
            {
                SetCellValue(cell, rawText);
            }

            sumRow.Append(cell);
        }

        sumTemplateRow.Remove();
    }

    /// <summary>
    ///     提取 {{Sum(xxx)}} 模板中的表达式部分。
    /// </summary>
    private static string? ExtractSumExpression(string? rawText)
    {
        if (string.IsNullOrWhiteSpace(rawText) || !rawText.Contains("Sum(", StringComparison.OrdinalIgnoreCase))
            return null;

        var inner = TemplateCellOccupyRegex().Replace(rawText, string.Empty).Trim();
        var start = inner.IndexOf("Sum(", StringComparison.OrdinalIgnoreCase);
        var end = inner.IndexOf(')', start + 4);
        if (start < 0 || end <= start) return null;

        return inner.Substring(start + 4, end - start - 4).Trim();
    }

    /// <summary>
    ///     根据表达式对实体集合或其子集合求和。
    /// </summary>
    private static double CalculateSumValue<T>(IEnumerable<T> source, string expression)
    {
        double sumValue = 0;
        var entityType = typeof(T);

        if (expression.Contains("[]"))
        {
            var parts = expression.Split('.', StringSplitOptions.RemoveEmptyEntries);
            var idxWithArray = Array.FindIndex(parts, p => p.Contains("[]"));
            if (idxWithArray < 0) return sumValue;
            var collectionName = parts[idxWithArray].Replace("[]", string.Empty);
            var childPropName = parts[^1];
            var collProp = entityType.GetProperty(collectionName);
            if (collProp == null) return sumValue;
            foreach (var item in source)
            {
                if (collProp.GetValue(item) is not IEnumerable collection) continue;
                sumValue +=
                    (from child in collection.OfType<object>()
                        let childProp = child.GetType().GetProperty(childPropName)
                        select new { childProp, child })
                    .Select(a => ParseNumeric(a.childProp.GetValue(a.child))).Sum();
            }
        }
        else
        {
            var prop = entityType.GetProperty(expression);
            if (prop == null) return sumValue;
            sumValue += source.Sum(item => ParseNumeric(prop.GetValue(item)));
        }

        return sumValue;
    }

    /// <summary>
    ///     将对象值转换为数值类型，无法解析时返回 0。
    /// </summary>
    private static double ParseNumeric(object? value)
    {
        return value != null && double.TryParse(
            Convert.ToString(value, CultureInfo.InvariantCulture),
            NumberStyles.Any,
            CultureInfo.InvariantCulture,
            out var result)
            ? result
            : 0;
    }

    /// <summary>
    ///     获取单元格值
    /// </summary>
    private static string GetCellValue(Cell cell, WorkbookPart workbookPart)
    {
        if (cell.DataType == null || cell.DataType.Value != CellValues.SharedString) return cell.InnerText;
        var sharedStringTablePart = workbookPart.SharedStringTablePart;
        if (sharedStringTablePart?.SharedStringTable == null) return cell.InnerText;
        var sharedStringTable = sharedStringTablePart.SharedStringTable;
        if (int.TryParse(cell.InnerText, out var id) &&
            id < sharedStringTable.Elements<SharedStringItem>().Count())
        {
            return sharedStringTable.Elements<SharedStringItem>().ElementAt(id).InnerText;
        }

        return cell.InnerText;
    }

    /// <summary>
    ///     设置单元格值
    /// </summary>
    private static void SetCellValue(Cell cell, dynamic value)
    {
        cell.CellValue?.Remove();
        cell.InlineString?.Remove();

        switch (value)
        {
            case string strValue when string.IsNullOrEmpty(strValue):
                cell.DataType = CellValues.String;
                cell.CellValue = new CellValue("");
                break;
            case string strValue:
                cell.DataType = CellValues.String;
                cell.CellValue = new CellValue(strValue);
                break;
            case double or int or float or decimal:
                cell.DataType = CellValues.Number;
                cell.CellValue = new CellValue(Convert.ToDouble(value).ToString(CultureInfo.InvariantCulture));
                break;
            case DateTime dateValue:
                cell.DataType = CellValues.Number;
                cell.CellValue = new CellValue(dateValue.ToOADate().ToString(CultureInfo.InvariantCulture));
                break;
            case bool boolValue:
                cell.DataType = CellValues.Boolean;
                cell.CellValue = new CellValue(boolValue);
                break;
            default:
                cell.DataType = CellValues.String;
                cell.CellValue = new CellValue(value.ToString() ?? "");
                break;
        }
    }

    /// <summary>
    ///     创建单元格并复制样式
    /// </summary>
    private static Cell CreateCell(Cell templateCell, uint rowIndex, int columnIndex)
    {
        var columnName = GetColumnName(columnIndex);
        var cellReference = $"{columnName}{rowIndex}";

        var newCell = new Cell
        {
            CellReference = cellReference, StyleIndex = templateCell.StyleIndex, DataType = templateCell.DataType
        };

        // 复制单元格格式属性
        if (templateCell.CellFormula != null)
        {
            newCell.CellFormula = (CellFormula)templateCell.CellFormula.CloneNode(true);
        }

        return newCell;
    }

    /// <summary>
    ///     应用单元格合并
    /// </summary>
    private static void ApplyMergedRegions(Worksheet worksheet,
        List<(uint startRow, uint endRow, int startCol, int endCol)> mergedRegions)
    {
        if (mergedRegions.Count == 0) return;

        var mergeCells = worksheet.GetFirstChild<MergeCells>();
        if (mergeCells == null)
        {
            mergeCells = new MergeCells();
            worksheet.InsertAfter(mergeCells, worksheet.GetFirstChild<SheetData>());
        }

        foreach (var (startRow, endRow, startCol, endCol) in mergedRegions)
        {
            var startColumnName = GetColumnName(startCol);
            var endColumnName = GetColumnName(endCol);
            var reference = $"{startColumnName}{startRow}:{endColumnName}{endRow}";

            var mergeCell = new MergeCell { Reference = reference };
            mergeCells.Append(mergeCell);
        }

        mergeCells.Count = (uint)mergeCells.Elements<MergeCell>().Count();
    }

    /// <summary>
    ///     获取列名（A, B, C, ..., AA, AB, ...）
    /// </summary>
    private static string GetColumnName(int columnIndex)
    {
        var columnName = "";
        while (columnIndex >= 0)
        {
            columnName = (char)('A' + columnIndex % 26) + columnName;
            columnIndex = columnIndex / 26 - 1;
        }

        return columnName;
    }

    /// <summary>
    ///     获取属性值
    /// </summary>
    /// <param name="property">属性</param>
    /// <param name="entity">实体</param>
    /// <returns></returns>
    private static dynamic GetPropertyValue(PropertyInfo property, object entity)
    {
        // 数组
        if (property.PropertyType.IsArray)
        {
            var value = property.GetValue(entity);
            return value is not null ? JsonSerializer.Serialize(value) : "";
        }

        // 枚举
        if (property.PropertyType.IsEnum)
        {
            return property.GetValue(entity) is System.Enum value ? EnumHelper.GetDescription(value) : "";
        }

        // 布尔
        if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?))
        {
            return property.GetValue(entity) is bool value ? value ? "是" : "否" : "";
        }

        // 时间
        if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?))
        {
            var value = property.GetValue(entity);
            return value is not null ? (DateTime)value : "";
        }

        // 值类型
        if (property.PropertyType == typeof(short) ||
            property.PropertyType == typeof(short?) ||
            property.PropertyType == typeof(int) ||
            property.PropertyType == typeof(int?) ||
            property.PropertyType == typeof(float) ||
            property.PropertyType == typeof(float?) ||
            property.PropertyType == typeof(double) ||
            property.PropertyType == typeof(double?) ||
            property.PropertyType == typeof(decimal) ||
            property.PropertyType == typeof(decimal?))
        {
            var value = property.GetValue(entity);
            return value is not null ? Convert.ToDouble(value) : "";
        }

        // 字符串类型
        if (property.PropertyType != typeof(string)) return "";
        {
            var value = property.GetValue(entity);
            return value is not null ? value.ToString()! : "";
        }
    }

    #endregion

    #region 枚举

    /// <summary>
    ///     列元数据类型。
    /// </summary>
    private enum ColumnKind
    {
        /// <summary>
        ///     固定文本列。
        /// </summary>
        PlainText,

        /// <summary>
        ///     实体的简单属性列。
        /// </summary>
        SimpleProperty,

        /// <summary>
        ///     实体的嵌套属性列。
        /// </summary>
        NestedProperty,

        /// <summary>
        ///     集合子项的属性列。
        /// </summary>
        CollectionProperty,

        /// <summary>
        ///     自动生成的行号列。
        /// </summary>
        RowIndex
    }

    #endregion

    #region 实体

    /// <summary>
    ///     列的模板与运行期上下文元数据。
    /// </summary>
    private sealed class ColumnMeta
    {
        /// <summary>
        ///     列索引，从 0 开始。
        /// </summary>
        public int ColumnIndex { get; init; }

        /// <summary>
        ///     模板单元格，用于复制样式。
        /// </summary>
        public Cell TemplateCell { get; init; } = null!;

        /// <summary>
        ///     模板的原始文本。
        /// </summary>
        public string? RawText { get; init; }

        /// <summary>
        ///     当前列的类型。
        /// </summary>
        public ColumnKind Kind { get; set; }

        /// <summary>
        ///     是否需要在数据块中进行行合并。
        /// </summary>
        public bool ShouldMerge { get; set; }

        /// <summary>
        ///     简单属性名称。
        /// </summary>
        public string? PropertyName { get; set; }

        /// <summary>
        ///     嵌套属性的父属性名称。
        /// </summary>
        public string? ParentPropertyName { get; set; }

        /// <summary>
        ///     嵌套属性的子属性名称。
        /// </summary>
        public string? ChildPropertyName { get; set; }

        /// <summary>
        ///     是否来自集合属性。
        /// </summary>
        public bool IsCollection { get; set; }

        /// <summary>
        ///     集合属性名称。
        /// </summary>
        public string? CollectionPropertyName { get; set; }

        /// <summary>
        ///     集合子项的属性名称。
        /// </summary>
        public string? CollectionItemPropertyName { get; set; }

        /// <summary>
        ///     运行时持有的集合引用。
        /// </summary>
        public IList? CurrentChildren { get; set; }
    }

    #endregion
}